module booth(
iClk, // input clock
iReset, // reset signal
iReady, // indicates inputs are ready
oDone, // indicates that the result is ready
iMultiplier, // 8-bit multiplier [7:0]
iMultiplicand, // 8-bit multiplicand [7:0]
oProduct // 16-bit product [15:0]
);
input [7:0] iMultiplier;
input [7:0] iMultiplicand;
input iClk;
input iReset;
input iReady;

output oDone;
output [15:0]oProduct;

//wires for adding on each shifts//
wire [7:0] sum1;
wire [7:0] sum2;
wire [7:0] sum3;
wire [7:0] sum4;
wire [7:0] sum5;
wire [7:0] sum6;
wire [7:0] sum7;
wire [7:0] sum8;


wire [15:0] buffer00;
wire [7:0] buffer01;
wire [15:0] buffer02;
wire [7:0] buffer03;
wire [15:0] buffer04;
wire [7:0] buffer05;
wire [15:0] buffer06;
wire [7:0] buffer07;
wire [15:0] buffer08;
wire [7:0] buffer09;
wire [15:0] buffer10;
wire [7:0] buffer11;
wire [15:0] buffer12;
wire [7:0] buffer13;
wire [15:0] buffer14;
wire [7:0] buffer15;


//determine shifted values//

//determine whether it should be added or subtract or nothing on each bit//
booth_determine d0(iMultiplicand, iMultiplier[0], 1'b0, sum1);
booth_determine d1(iMultiplicand, iMultiplier[1], iMultiplier[0], sum2);
booth_determine d2(iMultiplicand, iMultiplier[2], iMultiplier[1], sum3);
booth_determine d3(iMultiplicand, iMultiplier[3], iMultiplier[2], sum4);
booth_determine d4(iMultiplicand, iMultiplier[4], iMultiplier[3], sum5);
booth_determine d5(iMultiplicand, iMultiplier[5], iMultiplier[4], sum6);
booth_determine d6(iMultiplicand, iMultiplier[6], iMultiplier[5], sum7);
booth_determine d7(iMultiplicand, iMultiplier[7], iMultiplier[6], sum8);

//now, real add/subtract while shifting//
assign buffer00={8'b0000_0000,iMultiplier[7:0]}; //initializing

booth_adder a1(sum1, buffer00[15:8], buffer01[7:0]);
assign buffer02={buffer01[7], buffer01,buffer00[7:1]};

booth_adder a2(sum2, buffer02[15:8], buffer03);
assign buffer04={buffer03[7], buffer03, buffer02[7:1]};

booth_adder a3(sum3, buffer04[15:8], buffer05);
assign buffer06={buffer05[7], buffer05, buffer04[7:1]};

booth_adder a4(sum4, buffer06[15:8], buffer07);
assign buffer08={buffer07[7], buffer07, buffer06[7:1]};

booth_adder a5(sum5, buffer08[15:8], buffer09);
assign buffer10={buffer09[7], buffer09, buffer08[7:1]};

booth_adder a6(sum6, buffer10[15:8], buffer11);
assign buffer12={buffer11[7], buffer11, buffer10[7:1]};

booth_adder a7(sum7, buffer12[15:8], buffer13);
assign buffer14={buffer13[7], buffer13, buffer12[7:1]};

booth_adder a8(sum8, buffer14[15:8], buffer15);
assign oProduct={buffer15[7], buffer15, buffer14[7:1]};

endmodule


//module adder : 8+8 full adder//
module booth_adder(
input [7:0] a, 
input [7:0] b,
output [7:0] sum
);

wire [7:0] c; //carry between bits
wire [23:0] middle;

assign c[0]=0; //assign first carry

xor(sum[0],b[0],c[0],a[0]); //determining sum
and(middle[0], a[0], b[0]); 
and(middle[1], a[0], c[0]);
and(middle[2], b[0], c[0]);
or(c[1], middle[0], middle[1], middle[2]);

xor(sum[1],b[1],c[1],a[1]); //determining sum
and(middle[3], a[1], b[1]); 
and(middle[4], a[1], c[1]);
and(middle[5], b[1], c[1]);
or(c[2], middle[3], middle[4], middle[5]);

xor(sum[2],b[2],c[2],a[2]); //determining sum
and(middle[6], a[2], b[2]); 
and(middle[7], a[2], c[2]);
and(middle[8], b[2], c[2]);
or(c[3], middle[6], middle[7], middle[8]);

xor(sum[3],b[3],c[3],a[3]); //determining sum
and(middle[9], a[3], b[3]); 
and(middle[10], a[3], c[3]);
and(middle[11], b[3], c[3]);
or(c[4], middle[9], middle[10], middle[11]);

xor(sum[4],b[4],c[4],a[4]); //determining sum
and(middle[12], a[4], b[4]); 
and(middle[13], a[4], c[4]);
and(middle[14], b[4], c[4]);
or(c[5], middle[12], middle[13], middle[14]);

xor(sum[5],b[5],c[5],a[5]); //determining sum
and(middle[15], a[5], b[5]); 
and(middle[16], a[5], c[5]);
and(middle[17], b[5], c[5]);
or(c[6], middle[15], middle[16], middle[17]);

xor(sum[6],b[6],c[6],a[6]); //determining sum
and(middle[18], a[6], b[6]); 
and(middle[19], a[6], c[6]);
and(middle[20], b[6], c[6]);
or(c[7], middle[18], middle[19], middle[20]);

xor(sum[7],b[7],c[7],a[7]); //determining sum
//last carry will be disgarded//

endmodule


//module determine : determine 8bit value whether it should be added or subtracted//
module booth_determine(
input [7:0] a, //value should be determined
input cbit, //current bit
input rbit, //right bit
output [7:0] b
);

wire x,y; // if x=1, add should be processed. if y=1, subtract should be processed.
wire [1:0] n; //for not gate
wire [7:0] comp; //compliment of 'a'
wire middle[15:0]; //wire between gate & gate
wire forcarry[1:0]; //wire for obtaining carry bit

not(n[0], cbit); //cbit'
not(n[1], rbit); //rbit'

and(x,n[0],rbit); //if cbit=0 & rbit=1, add will be enabled.
and(y,cbit,n[1]); //if cbit=1 & rbit=0, subtract will be enabled.

//obtaining 2's compliment of 'a'//
// I. reverse //

wire [7:0] rev;

not(rev[0], a[0]);
not(rev[1], a[1]);
not(rev[2], a[2]);
not(rev[3], a[3]);
not(rev[4], a[4]);
not(rev[5], a[5]);
not(rev[6], a[6]);
not(rev[7], a[7]);

// II. adding 0000_0001 //

wire [7:0] one;
assign one=8'b0000_0001;
booth_adder com(rev, one, comp);

//real determining//
and(middle[0], x, a[0]);
and(middle[1], y, comp[0]);
or(b[0], middle[0], middle[1]);

and(middle[2], x, a[1]);
and(middle[3], y, comp[1]);
or(b[1], middle[2], middle[3]);

and(middle[4], x, a[2]);
and(middle[5], y, comp[2]);
or(b[2], middle[4], middle[5]);

and(middle[6], x, a[3]);
and(middle[7], y, comp[3]);
or(b[3], middle[6], middle[7]);

and(middle[8], x, a[4]);
and(middle[9], y, comp[4]);
or(b[4], middle[8], middle[9]);

and(middle[10], x, a[5]);
and(middle[11], y, comp[5]);
or(b[5], middle[10], middle[11]);

and(middle[12], x, a[6]);
and(middle[13], y, comp[6]);
or(b[6], middle[12], middle[13]);

and(middle[14], x, a[7]);
and(middle[15], y, comp[7]);
or(b[7], middle[14], middle[15]);

endmodule

